<!DOCTYPE HTML>
<html lang="zh" style="font-size:100px">

<head>
    <meta charset="utf-8" />
    <title>2018年上半年飞过的地方 - Hello全视界</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
    <script src="../lib/three.js"></script>
    <!-- <script src="../lib/vue.js"></script> -->
    <script src="../control_stick/util.js"></script>
    <script src="../control_stick/stick.js"></script>

    <style>
        html,
        body,
        #app {
            padding: 0;
            margin: 0;
            overflow: hidden;
            width: 100vw;
            height: 100vh;
            min-height: 100vh;
        }

        body {
            font-family: sans-serif;
            line-height: 1em;
            font-size: 0.16rem;
        }

        button {
            font-size: 0.16rem;
            font-family: sans-serif;
        }

        div {
            box-sizing: border-box;
        }

        ul,
        li {
            list-style: none;
            margin: 0;
            padding: 0
        }

        p {
            margin: 0;
        }

        #app {
            position: relative;
        }

        .logo {
            position: absolute;
            margin: 0.2rem 0 0 0.4rem;
            z-index: 999;

        }

        .logo>img {
            width: 2rem;
        }

        .panoWrap {
            position: absolute;
            overflow: hidden;
            cursor: -webkit-grab;
        }

        .panoWrap:active {
            cursor: -webkit-grabbing;
        }

        .panoControls {
            position: absolute;
            display: flex;
            justify-content: flex-end;
            /* width: 100%; */
            align-items: center;
            top: -0.6rem;
            padding: 0 0.2rem;
            right: 0px;
        }

        .panoControls>button,
        .panoControls>div,
        .panoControls>a,
        .panoControls>input {
            pointer-events: all;
        }

        button.holaGreen {
            background: #1c1c1c;
            border: #62d128 solid 2px;
            color: #62d128;
        }

        .panoControls button {
            padding: 0.1rem 0.2rem;
            display: block;
            margin: 0 10px
        }

        .panoPanelBottom button.rollOutBtn {
            position: absolute;
            height: 2em;
            top: -2em;
        }

        .panoPanelBottom {
            position: absolute;
            width: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            bottom: 0;
            transition: 0.4s ease bottom;
            padding-top: 0.1rem;
        }

        .panoPanelBottom.fold {
            bottom: -1.6rem;
        }


        .panoList {
            width: 100%;
            height: 1.7rem;
        }

        .panoList>ul {
            display: flex;
            color: #fff;
            margin: 0 auto;
            margin-bottom: 1em;
        }

        .panoList>ul li {
            display: flex;
            flex-direction: column;
            color: #fff;
            justify-content: center;
            margin: 0 10px;
            align-items: center;
        }

        .panoList>ul li>img.panoThumb {
            width: 2rem;
            display: block;
            min-width: 2rem;
            flex-shrink: 0;
        }

        .panoList>ul li>p.panoTitle {
            line-height: 1.5em;
            text-align: center;
            flex-shrink: 0;
            display: block;
            word-break: keep-all;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        .scrollBar {
            width: 2rem;
            position: absolute;
            display: flex;
            align-items: center;
            left: 20px;
        }

        .scrollBar>.stick {
            position: absolute;
            display: block;
            width: 0.2rem;
            height: 0.2rem;
            background-color: #62d128;
            border: #62d128 solid 2px;
            border-radius: 50%;
            flex-shrink: 0;
        }

        .scrollBar>.bar {
            width: 100%;
            display: block;
            height: 2px;
            background: #62d128;
        }
    </style>
</head>

<body>
    <div id="app" v-cloak>
        <div class="logo">
            <img src="../logo.svg" />
        </div>
        <div class="panoWrap"></div>
        <div class="panoPanelBottom" :class="{'fold':isPanoPanelBottomFold}">
            <button v-on:click="panoListRollToggle" class="rollOutBtn">展开收起</button>

            <div class="panoList">
                <ul>
                    <li v-for="(pano,index) in panos">
                        <img class="panoThumb" @click="panoChange(index)" :src="panoThumbPath+pano.imgThumb" />
                        <p class="panoTitle">{{pano.desc}}</p>
                    </li>
                </ul>
                <div class="scrollBar" data-role="miniScrollBar">
                    <span class="stick"></span>
                    <div class="bar"></div>
                </div>
            </div>

            <div class="panoControls">
                <button data-role="btn" data-todo="shot" class="fullScreenBtn holaGreen">截屏</button>
                <button data-role="btn" data-todo="toggleVR" class="fullScreenBtn holaGreen">VR</button>
                <button data-role="btn" data-todo="toggleFullScreen" class="fullScreenBtn holaGreen">全屏</button>
                <button data-role="btn" data-todo="toggleOrient" class="fullScreenBtn holaGreen">陀螺仪</button>
                <button data-role="btn" data-todo="togglePointer" class="fullScreenBtn holaGreen">鼠标</button>

            </div>
        </div>
    </div>

    <script src="./pano_array.js"></script>
    <script src="./position2_array.js"></script>

    <script>
        'use strict';

        // var panoApp = new Vue({
        //     el: '#app',
        //     data: {
        //         fullScreenStatus: document.fullscreenElement,
        //         isPanoPanelBottomFold: false,

        //         panos: panos,
        //         currentIndex: 0,

        //         //配置全景图文件夹基地址
        //         panoBasePath: threeStage.panoBasePath,
        //         panoThumbPath: threeStage.panoThumbPath,

        //         panoGeoCood: 0
        //     },
        //     methods: {
        //         mounted: function () {

        //         },

        //         panoListRollToggle: function () {
        //             if (this.isPanoPanelBottomFold) {
        //                 this.isPanoPanelBottomFold = false
        //             } else {
        //                 this.isPanoPanelBottomFold = true
        //             }

        //         },
        //         fullScreen: function () {
        //             if (!document.fullscreenElement) {
        //                 document.body.requestFullscreen();
        //             } else {
        //                 document.exitFullscreen();
        //             }
        //         },
        //         panoChange: function (listNum) {
        //             console.log(this.currentIndex + ' ' + listNum)

        //             panoImgTex = new THREE.TextureLoader().load(panoBasePath + panos[listNum].imgName,
        //                 function (e) {
        //                     e.image.src = panoBasePath + panos[listNum].imgName;
        //                     if (listNum == this.currentIndex) {
        //                         return
        //                     } else {
        //                         this.currentIndex = listNum;
        //                         panoImgTex.needsUpdate = true;
        //                         spriteGroup.children = [];//在切换之前把当前全景上所有的sprite poi清空

        //                         //切换之后，读取相关数据，将sprite加入场景

        //                         panoImgTex.dispose();
        //                         panoPhotoMaterial.map = e;
        //                         panoImgTex.anisotropy = 8;
        //                         panoImgTex.needsUpdate = false;
        //                     }
        //                 })
        //         }
        //     }
        // });

        //THREEJS场景部分
        var ThreeStage = function () {
            // this.bind(threeStage);
            var _this = this;
            console.log(this);

            //检测是否存在用户交互
            _this.userInteract = false;

            //标识是否暂停旋转动画
            _this.pauseRotete = false;

            //配置全景图文件夹基地址
            _this.panoBasePath = "./pano_images/";
            _this.panoThumbPath = "./pano_thumb/";

            //存储全景图列表，未来通过Ajax来获得。
            //全景图列表中保存的经纬度：若来自用户的相机，在使用时应当首先接入百度地图来进行位置修正，返回百度地图中的坐标
            // _this.panosList=[];
            _this.panosList = panos;

            //存储百度地图地点列表，未来通过访问百度地图API来获得
            // _this.neighborList=[];
            _this.neighborList = positions;

            //当前全景图索引，未来试图通过Ajax来获得首次载入时的索引
            _this.currentIndex = 0;

            //当前的鼠标坐标
            _this.pointData = {
                originX: 0,
                originY: 0,
                offsetX: 0,
                offsetY: 0,
                originTheta: 0,
                originPhi: 0
            }

            //将事件中的this进行bind
            _this.eventHandlerBind();

            //初始化场景1
            _this.sceneInit();

            //加入鼠标事件
            _this.attachController('mouse');
            // _this.attachController('orient');

            //传入全景图索引值，来确定应当以哪一张全景图来开场
            _this.panoInit(_this.currentIndex);

            //初始化sprite
            _this.spriteGroupInit();
            _this.addPoi();

            _this.btnTodoHandler();


        }
        //基本场景初始化
        ThreeStage.prototype.sceneInit = function () {

            var scene = new THREE.Scene();

            //用于将scene暴露到全局，仅在调试时使用
            window.scene = scene;

            //默认相机为位于原点的透视相机
            //fov,aspect,near,far
            var defaultCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            defaultCamera.name = "defaultCamera";

            var cameraGroup = new THREE.Group();
            cameraGroup.name = "cameraGroup"
            cameraGroup.add(defaultCamera);
            scene.add(cameraGroup);

            var renderer = new THREE.WebGLRenderer({
                "antialias": true
            });

            //加光
            var light = new THREE.AmbientLight(0xffffff, 2);
            scene.add(light);

            //尝试将渲染尺寸乘以设备像素比，防止手机浏览器渲染时产生锯齿。
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.setPixelRatio(window.devicePixelRatio);

            //将渲染器 - Canvas元素插入到DOM中
            var panoWrap = document.getElementById('app').querySelector('.panoWrap');
            panoWrap.appendChild(renderer.domElement);

            //摄像机目标
            var cameraTarget = new THREE.Object3D();
            cameraTarget.name = "cameraTarget";
            //第一个值为半径，第二个值为上下旋转角，第三个值为平面极坐标的旋转角
            var panoSphereRadius = 10;
            var targetSphereCood = new THREE.Spherical(panoSphereRadius, util.degToRad(225), 0);
            cameraTarget.position.setFromSpherical(targetSphereCood);

            scene.add(cameraTarget);



            //添加窗口缩放事件
            window.addEventListener('resize', this.resizeHandler.bind(this), false);

            this.scene = scene;
            this.camera = defaultCamera;
            this.cameraGroup = cameraGroup;
            this.renderer = renderer;
            this.panoWrap = panoWrap;
            this.light = light;
            this.cameraTarget = cameraTarget;
            this.targetSphereCood = targetSphereCood;
            this.panoSphereRadius = panoSphereRadius;

            console.log(this.targetSphereCood);

        };
        //全景球初始化
        ThreeStage.prototype.panoInit = function (panoIndex) {
            //全景球半径为10
            var panoGeometry = new THREE.SphereBufferGeometry(10, 36, 36);
            //直接将x设为-1，使得所有面朝向内测
            panoGeometry.scale(-1, 1, 1);

            //载入贴图
            var panoImgTex = new THREE.TextureLoader().load(this.panoBasePath + this.panosList[panoIndex].imgName);
            //设置该值以减缓球面贴图南北两极的锯齿现象
            panoImgTex.anisotropy = 8;

            var panoPhotoMaterial = new THREE.MeshStandardMaterial({
                "map": panoImgTex,
                "color": 0xffffff,
            });
            var panoSphere = new THREE.Mesh(panoGeometry, panoPhotoMaterial);
            this.scene.add(panoSphere);

            this.panoGeometry = panoGeometry;
            this.panoImgTex = panoImgTex;
            this.panoPhotoMaterial = panoPhotoMaterial;
            this.panoSphere = panoSphere;

            console.log(this.camera)

            this.renderer.render(this.scene, this.camera);

            this.panoRotationAnimate();

            //阻止默认的鼠标右键菜单弹出
            this.panoWrap.addEventListener('contextmenu', function (e) {
                e.preventDefault();
            }, false);

        };

        //与事件相关的各种UI逻辑
        ThreeStage.prototype.eventHandlerBind = function () {
            this.eventBind = {};
            //事件处理函数中this指向的是addEventListener的元素，因此需要bind
            //但使用bind会生成一个新的函数，没法removeEventListener，在此先将函数预先bind
            this.eventBind.deviceOrientationHandler = this.deviceOrientationHandler.bind(this);
            this.eventBind.orientationChangeHandler = this.orientationChangeHandler.bind(this);
            this.eventBind.pointHandler = this.pointHandler.bind(this);
            this.eventBind.pointRayHandler = this.pointRayHandler.bind(this);
            this.eventBind.mouseScrollHandler = this.mouseScrollHandler.bind(this);
        }
        //全景交互
        ThreeStage.prototype.attachController = function (eventType) {
            switch (eventType) {
                //陀螺仪和鼠标之间暂时没想到并存的办法。
                case 'mouse':
                case 'touch': {
                    this.pauseRotete = false;
                    window.removeEventListener("deviceorientation", this.eventBind.deviceOrientationHandler, false);
                    window.removeEventListener('orientationchange', this.eventBind.orientationChangeHandler, false);
                    this.panoWrap.addEventListener("mousedown", this.eventBind.pointHandler, false);
                    this.panoWrap.addEventListener('touchstart', this.eventBind.pointHandler, false);
                    this.panoWrap.addEventListener("mousedown", this.eventBind.pointRayHandler, false);
                    this.panoWrap.addEventListener("mousewheel", this.eventBind.mouseScrollHandler, false);
                    break;
                };
                case 'orient': {
                    this.panoWrap.removeEventListener("mousedown", this.eventBind.pointHandler, false);
                    this.panoWrap.removeEventListener('touchstart', this.eventBind.pointHandler, false);
                    this.panoWrap.removeEventListener("mousedown", this.eventBind.pointRayHandler, false);
                    this.panoWrap.removeEventListener("mousewheel", this.eventBind.mouseScrollHandler, false);
                    window.addEventListener("deviceorientation", this.eventBind.deviceOrientationHandler, false);
                    window.addEventListener('orientationchange', this.eventBind.orientationChangeHandler, false);
                    break;
                };
            }
        };
        //DOM控件交互
        //画面控制
        ThreeStage.prototype.btnTodoHandler = function () {
            var _this=this;
            document.querySelector('.panoControls').addEventListener('click', function (e) {
                switch (e.target.dataset.todo) {
                    case 'toggleFullScreen': {
                        fullScreen(document.querySelector('body'));
                        break;
                    };
                    case 'toggleVR': {
                        _this.vrHandler();
                        break;
                    };
                    case 'toggleOrient': {
                        _this.attachController('orient');
                        break;
                    };
                    case 'togglePointer':{
                        _this.attachController('mouse')
                        break;
                    }
                    case 'shot': {
                        _this.shot(document.querySelector('.panoWrap').getElementsByTagName('canvas')[0]);
                        break;
                    }
                }
            }, false)
        }

        //全景球旋转动画    //setInterval(animate,100);
        ThreeStage.prototype.panoRotationAnimate = function () {

            //交互部分
            //判断是否存在用户交互
            //无交互、且无暂停
            if (!this.userInteract) {
                if (!this.pauseRotete) {
                    this.targetSphereCood.theta += util.degToRad(0.075);
                    this.cameraTarget.position.setFromSpherical(this.targetSphereCood);
                    //判断当前相机是否为相机阵列，如果是的话在请求动画时需要遍历更新子相机
                    if (this.camera instanceof THREE.ArrayCamera === false) {
                        this.camera.lookAt(this.cameraTarget.position);
                        //console.log(this.cameraTarget.position);
                    } else {
                        for (var i = 0; i < this.camera.cameras.length; i++) {
                            this.camera.cameras[i].lookAt(this.cameraTarget.position);
                        }
                    }
                }
            }

            this.renderer.render(this.scene, this.camera);
            // console.log(this.renderer)

            //注意this指向，在定时器中this指向window
            requestAnimationFrame(this.panoRotationAnimate.bind(this));
        }
        /*
            交互方式：
            改变全景照片的方向
            鼠标/触摸：在屏幕上上下滑动改变上下旋转角，左右滑动更改平面旋转角；
            设备朝向：移动设备改变摄像机目标的位置
            改变摄像机的FOV
            鼠标滚轮：向前放大，向后缩小
        */
        //处理鼠标或者触摸屏事件
        ThreeStage.prototype.pointHandler = function (e) {
            //鼠标拖动全景球事件由鼠标左键来触发
            if (e.type.match('mouse') || e.type == 'click') {
                if (e.button != 0) {
                    return;
                }
            }

            var evtType = e.type;

            // e.preventDefault();

            if (e.type.match('touch')) {
                e = e.touches[0];
            }

            //事件处理函数中this指向的是addEventListener的元素
            // console.log(this);

            switch (evtType) {
                case "touchstart":
                case "mousedown": {
                    this.userInteract = true;
                    //得到鼠标点击位置
                    this.pointData.originX = e.clientX;
                    this.pointData.originY = e.clientY;

                    //
                    this.pointData.originTheta = this.targetSphereCood.theta;
                    this.pointData.originPhi = this.targetSphereCood.phi;
                    //

                    this.panoWrap.addEventListener("mousemove", this.pointHandler.bind(this), false);
                    this.panoWrap.addEventListener("mouseup", this.pointHandler.bind(this), false);

                    this.panoWrap.addEventListener("touchmove", this.pointHandler.bind(this), false);
                    this.panoWrap.addEventListener("touchend", this.pointHandler.bind(this), false);

                    break;
                }
                case "touchmove":
                case "mousemove": {
                    if (this.userInteract) {

                        //鼠标移动时计算鼠标的偏移量
                        this.pointData.offsetX = e.clientX - this.pointData.originX;
                        this.pointData.offsetY = e.clientY - this.pointData.originY;

                        //
                        this.targetSphereCood.theta = this.pointData.offsetX * 0.005 + this.pointData.originTheta;
                        // console.log(util.radToDeg(sphereCood.phi))

                        var phi = this.pointData.offsetY * 0.005 + this.pointData.originPhi;
                        //限制上下俯仰角度，以防万向锁。来自THREEJS
                        this.targetSphereCood.phi = util.clamp(phi, util.degToRad(181), util.degToRad(359));

                        // console.log(sphereCood.theta + ' ' + sphereCood.phi)

                        this.cameraTarget.position.setFromSpherical(this.targetSphereCood);
                        this.camera.lookAt(this.cameraTarget.position);

                    }
                    break;
                }

                case "touchend":
                case "mouseup": {
                    this.userInteract = false;

                    this.panoWrap.removeEventListener("mouseup", this.pointHandler.bind(this), false);
                    this.panoWrap.removeEventListener("touchend", this.pointHandler.bind(this), false);

                    this.panoWrap.removeEventListener("mousemove", this.pointHandler.bind(this), false);
                    this.panoWrap.removeEventListener("touchmove", this.pointHandler.bind(this), false);
                    break;
                }
            }
        }
        //处理窗口大小改变时三维场景的变化
        ThreeStage.prototype.resizeHandler = function (e) {
            this.renderer.setSize(window.innerWidth, window.innerHeight);
            this.camera.aspect = window.innerWidth / window.innerHeight;
            this.camera.updateProjectionMatrix();
        }

        //处理光线投射
        ThreeStage.prototype.pointRayHandler = function (e) {
            if (e.type.match('mouse') || e.type == 'click') {
                //如果按下的按键为鼠标左键则不进行光线投射
                if (e.button == 0) {
                    return;
                }
            }

            var mouse = new THREE.Vector2();

            // console.log(event);

            var raycaster = new THREE.Raycaster();

            e.preventDefault();

            //将浏览器坐标转换到Threejs坐标
            mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
            mouse.y = - (e.clientY / window.innerHeight) * 2 + 1;

            raycaster.setFromCamera(mouse, this.camera);
            console.log(this.camera);

            //一个数组，用于保存与射线相交叉的对象
            //数组下标按照物体远近来进行排序，下标越大越远
            var intersects = raycaster.intersectObjects(scene.children)

            //尝试把射线选中的除了全景球以外的元素删去
            //似乎可以用.filter(function(obj3d){return ...});来替换？
            var realIntersects = [];
            for (var i = 0; i < intersects.length; i++) {
                // console.log(intersects);
                if (intersects[i].object.geometry instanceof THREE.SphereBufferGeometry) {
                    realIntersects.push(intersects[i]);
                }
            }
            // console.log(realIntersects);
            var intersectPoint = realIntersects[0].point;
            console.log(intersectPoint);
        };

        //处理鼠标滚轮
        ThreeStage.prototype.mouseScrollHandler = function (e) {
            //主要是更改场景中相机的fov
        };

        //处理设备方向
        ThreeStage.prototype.orientationChangeHandler = function (e) {
            //console.log(e);
        }
        ThreeStage.prototype.deviceOrientationHandler = function (e) {

            this.pauseRotete = true;

            //这个值表示屏幕朝向，当屏幕朝向变的时候改变这个值
            //+-------+   +---------------+   +---------------+
            //|       |   |               |   |               |
            //|       |   |      +90    < |   | >     -90     |
            //|   0   |   |               |   |               |
            //|       |   +---------------+   +---------------+
            //|   ^   |                                  
            //+-------+                                  
            var screenOrientation = window.orientation || 0;//桌面端似乎不存在window.orientation

            //代码来自threejs  //
            var euler = new THREE.Euler();
            euler.set(util.degToRad(e.beta), util.degToRad(e.alpha), util.degToRad(-e.gamma), 'YXZ');//从传感器新建一个欧拉角

            var q0 = new THREE.Quaternion();
            var q1 = new THREE.Quaternion(- Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)); // - PI/2 around the x-axis
            var qn = new THREE.Quaternion().setFromEuler(euler);
            qn.multiply(q1);
            qn.multiply(q0.setFromAxisAngle(new THREE.Vector3(0, 0, 1), -screenOrientation));


            this.camera.setRotationFromQuaternion(qn)
            // this.cameraTarget.quaternion=qn;
            console.log(this.camera.quaternion)

            /*
            //尝试直接把旋转值对应坐标赋给cameraTarget，失败
            var targetOriginSphericalCood=new THREE.Spherical().setFromVector3(this.cameraTarget.position);

            //beta: 1~179deg
            targetOriginSphericalCood.phi=util.degToRad(util.clamp(-e.beta,-179,-1));
            targetOriginSphericalCood.theta=util.degToRad(e.alpha);

            // console.log(targetOriginSphericalCood.phi);

            var targetNewPosition=new THREE.Vector3().setFromSpherical(targetOriginSphericalCood);

            this.cameraTarget.position.x = targetNewPosition.x;
            this.cameraTarget.position.y = targetNewPosition.y;
            this.cameraTarget.position.z = targetNewPosition.z;

            this.camera.lookAt(this.cameraTarget.position);

            // console.log(this.cameraTarget.position)
            */
        };

        //场景中Sprite组初始化
        ThreeStage.prototype.spriteGroupInit = function () {
            var spriteOutterGroup = new THREE.Group();
            spriteOutterGroup.name = "spriteOutterGroup";
            var spriteGroup = new THREE.Group();

            spriteGroup.name = "spriteGroup";

            spriteGroup.scale.x = -1;
            spriteGroup.scale.y = -1;
            spriteGroup.rotation.y = util.degToRad(-90);

            spriteOutterGroup.add(spriteGroup);
            scene.add(spriteOutterGroup);

            this.spriteGroup = spriteGroup;
        }

        //切换到VR
        ThreeStage.prototype.vrHandler = function () {

            fullScreen(document.querySelector('.panoWrap'),false);
            this.attachController('orient');

            //设置左眼右眼
            var rightCamera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight / 2, 0.1, 1000);
            rightCamera.name = "rightCamera";
            var leftCamera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight / 2, 0.1, 1000);
            leftCamera.name = "leftCamera";

            //设置相机的边界
            leftCamera.bounds = new THREE.Vector4(0, 0, 0.5, 1);
            rightCamera.bounds = new THREE.Vector4(0.5, 0, 0.5, 1);


            //瞳距
            leftCamera.position.x = -0.2;
            rightCamera.position.x = 0.2;

            // leftCamera.lookAt(this.cameraTarget);
            // rightCamera.lookAt(this.cameraTarget);

            var hmdGlasses = new THREE.ArrayCamera([leftCamera, rightCamera]);

            hmdGlasses.name = "hmdGlasses";

            // hmdGlasses.lookAt(this.cameraTarget);

            hmdGlasses.add(leftCamera);
            hmdGlasses.add(rightCamera);

            this.cameraGroup.add(hmdGlasses);

            this.camera = hmdGlasses;

        }

        //poiBoard是独立组件，可在毕业设计其它场景（全景照片展示、完全虚拟场景、增强现实场景）中复用。
        //poiBoard生成器
        var poiBoardGenerator = function (posName, posDistance) {
            var icon = new Image();
            icon.src = "";
            // icon.id="icon";
            // document.body.appendChild(icon);
            var canvas = document.createElement('canvas');
            canvas.width = 1024;
            canvas.height = 256;
            var ctx = canvas.getContext("2d");
            ctx.fillStyle = "rgba(0,0,0,0.5)";
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            // ctx.fillRect(50, 60, 206, 206);
            //某些poi icon没画出来
            icon.addEventListener('load', function (e) {
                console.log(e);
                ctx.drawImage(icon, 40, 40, 176, 176);
            });

            ctx.moveTo(256, 33);
            ctx.lineTo(256, 222);
            ctx.strokeStyle = "#00ce00";
            ctx.lineWidth = 7;
            ctx.stroke();

            ctx.fillStyle = "#ffffff";
            ctx.font = '54px sans-serif';

            if (posName.length > 12) {
                var posName = posName.slice(0, 12) + '...';
            }
            ctx.fillText(posName, 300, 110);

            ctx.fillStyle = "#ffffff";
            ctx.font = '36px sans-serif';
            ctx.fillText(posDistance, 300, 180);

            document.body.appendChild(canvas);
            return canvas;
        }
        var poiSpriteGenerator = function (canvas) {
            //在所点击点随便添加一个物体
            var poiMap = new THREE.CanvasTexture(canvas);
            // poiMap.needsUpdate = false;
            //要使得poi板朝向摄像机，必须使用SpriteMaterial材质
            var poiMaterial = new THREE.SpriteMaterial({ map: poiMap, color: 0xffffff, transparent: true, depthTest: false });
            var poiObject = new THREE.Sprite(poiMaterial);
            poiObject.center = new THREE.Vector2(0, 0)
            var poiboardSize = [1024, 256];
            poiObject.scale.set(poiboardSize[0] * 0.0012, poiboardSize[1] * 0.0012, 1);

            return poiObject;
        }
        //计算poi与全景拍摄距离，并将得到的距离赋值给源对象
        var poiCalc = function (coodA, coodB) {
            var poiInfo = {
                distance: util.geoLength(coodA, coodB),
                angle: util.geoAngle(coodA, coodB)
            };
            return poiInfo;
        }

        //将poiBoard加入到场景中
        ThreeStage.prototype.addPoi = function () {
            var originP = this.panosList[this.currentIndex].geoCood;

            for (var i = 0; i < this.neighborList.length; i++) {
                this.neighborList[i].poiInfo = poiCalc(originP, this.neighborList[i].point);//算出poi与全景照片拍摄点的距离和角度
                console.log(this.neighborList[i].poiInfo);
                var distanceText;
                if (this.neighborList[i].poiInfo.distance > 1000) {
                    distanceText = (this.neighborList[i].poiInfo.distance / 1000).toFixed(1) + ' km';
                } else {
                    distanceText = this.neighborList[i].poiInfo.distance.toFixed(0) + ' m';
                }

                //生成poiBoard
                var poiCanvas = poiBoardGenerator(this.neighborList[i].title, distanceText);
                //生成sprite
                var poiObj = poiSpriteGenerator(poiCanvas);
                // console.log(poiObj);

                //有了角度、有了距离，算球坐标
                //俯仰角根据poi距离来确定，角度值在90~180之间
                console.log(this.neighborList[i].poiInfo.distance / 2000 * 180);
                var lengthVal = util.clamp(this.neighborList[i].poiInfo.distance / 2000 * this.panoSphereRadius, 0.2 * this.panoSphereRadius, this.panoSphereRadius * 0.3);//poi半径长度，poi越远值越大，但限制在给定范围内
                var pitchVal = util.degToRad(util.clamp(this.neighborList[i].poiInfo.distance / 2000 * 180 + util.rand(-20, 20), 75, 90));//poi球坐标的俯仰角，角度值在90~180之间。
                var azimuthVal = util.degToRad(this.neighborList[i].poiInfo.angle);//poi球坐标的方位角

                // console.log(lengthVal)
                var poiSpherical = new THREE.Spherical(lengthVal, pitchVal, azimuthVal);

                var poiCood = new THREE.Vector3().setFromSpherical(poiSpherical);
                // console.log(poiCood);
                poiObj.position.x = poiCood.x;
                poiObj.position.y = poiCood.y;
                poiObj.position.z = poiCood.z;

                this.spriteGroup.add(poiObj);

            }
        }

        //全景截图，相当于Canvas截取图片
        ThreeStage.prototype.shot = function (canvas) {
            //如果没有传入canvas元素或者传入的不是canvas元素，就默认将canvas参数设为获得的第一个canvas元素
            if (!(canvas instanceof HTMLCanvasElement)) {
                if (document.getElementsByTagName('canvas').length !== 0) {
                    canvas = document.getElementsByTagName('canvas')[0];
                } else {
                    return;
                }
            }


            //现渲染现截图，若不渲染就截图，会导致截到全黑画面
            this.renderer.render(this.scene, this.camera);
            console.log(this.renderer.domElement.toDataURL('image/jpeg', 0.92));

            // canvas.toBlob(
            //     function (blob) {
            //         console.log(blob)
            //     },
            //     'image/jpeg',
            //     0.92
            // );

        }

        //请求全屏
        //element：要进入全屏幕的元素
        //toggle：是否进行全屏幕切换，不传入就不切换
        function fullScreen(element, noToggle) {
            if (!document.fullscreenElement) {
                element.requestFullscreen();
            } else if (noToggle) {
                //如果传入了noToggle，就不要切换
                return;
            } else {
                document.exitFullscreen();
            }
        }

        var a = new ThreeStage;

    </script>
</body>

</html>